package main

import (
	"fmt"
	"log"
	"time"

	"gitee.com/barryzxy/gomodbus"
)

func main() {
	fmt.Println("=== 网关协议完整测试演示 ===")

	// 启动服务器
	go startServer()

	// 等待服务器启动
	time.Sleep(2 * time.Second)

	// 运行客户端测试
	runClientTests()
}

// startServer 启动测试服务器
func startServer() {
	fmt.Println("正在启动测试服务器...")

	// 创建TCP服务器
	server := gomodbus.NewTCPServer("127.0.0.1:5021", 5*time.Second)
	if server == nil {
		log.Fatal("创建服务器失败")
	}

	// 创建网关设备节点
	gatewayNode := modbus.NewNodeRegister(65, 0, 10, 0, 10, 0, 10, 0, 10)
	gatewayNode.InitGatewayDataStore(100)

	// 创建变送器设备节点
	transmitterNode := modbus.NewNodeRegister(1, 0, 10, 0, 10, 0, 10, 0, 10)
	transmitterNode.InitGatewayDataStore(100)

	// 添加节点到服务器
	server.AddNodes(gatewayNode, transmitterNode)

	// 启动服务器
	err := server.ListenAndServe()
	if err != nil {
		log.Printf("启动服务器失败: %v", err)
		return
	}

	fmt.Println("测试服务器已启动 (127.0.0.1:5021)")
}

// runClientTests 运行客户端测试
func runClientTests() {
	fmt.Println("\n开始客户端测试...")

	// 创建TCP客户端
	provider := modbus.NewTCPClientProvider("127.0.0.1:5021", modbus.TCPClientTimeout(5*time.Second))
	client := modbus.NewClient(provider)

	fmt.Println("\n=== 测试功能码 0x50: 读数据记录 ===")
	testReadDataRecords(client)

	fmt.Println("\n=== 测试功能码 0x51: 读当前数据 ===")
	testReadCurrentData(client)

	fmt.Println("\n=== 测试功能码 0x52: 写子设备参数 ===")
	testWriteSubDevParam(client)

	fmt.Println("\n=== 测试功能码 0x53: 写网关参数 ===")
	testWriteGatewayParam(client)

	fmt.Println("\n=== 测试完成 ===")
}

// testReadDataRecords 测试读数据记录
func testReadDataRecords(client modbus.Client) {
	// 测试数据对齐
	fmt.Println("1. 测试数据对齐 (读取对齐时间戳)")
	alignedTimestamp, err := client.GatewayReadDataRecordsAlign(65, 0)
	if err != nil {
		fmt.Printf("   错误: %v\n", err)
	} else {
		fmt.Printf("   对齐时间戳: %d (%s)\n", alignedTimestamp,
			time.Unix(int64(alignedTimestamp), 0).Format("2006-01-02 15:04:05"))
	}

	// 测试批量读取数据记录
	fmt.Println("2. 测试批量读取数据记录")
	records, err := client.GatewayReadDataRecords(65, 0)
	if err != nil {
		fmt.Printf("   错误: %v\n", err)
	} else {
		fmt.Printf("   成功读取 %d 条记录\n", len(records))
		if len(records) > 0 {
			latest := records[len(records)-1]
			fmt.Printf("   最新记录: 压力=%.2f %s, 电池=%d%%, 时间=%s\n",
				latest.Pressure,
				getPressureUnitName(latest.PressureUnit),
				latest.BatteryLevel,
				time.Unix(int64(latest.Timestamp), 0).Format("15:04:05"))
		}
	}
}

// testReadCurrentData 测试读当前数据
func testReadCurrentData(client modbus.Client) {
	fmt.Println("1. 测试读取网关当前数据 (地址 65)")
	record, err := client.GatewayReadCurrentData(65)
	if err != nil {
		fmt.Printf("   错误: %v\n", err)
	} else {
		fmt.Printf("   压力: %.2f %s\n", record.Pressure, getPressureUnitName(record.PressureUnit))
		fmt.Printf("   电池: %d%%\n", record.BatteryLevel)
		fmt.Printf("   连接: %s\n", getConnectionStatus(record.ConnectionStatus))
		fmt.Printf("   信号: %d级\n", record.SignalLevel)
		fmt.Printf("   时间: %s\n", time.Unix(int64(record.Timestamp), 0).Format("2006-01-02 15:04:05"))
	}

	fmt.Println("2. 测试读取变送器当前数据 (地址 1)")
	record, err = client.GatewayReadCurrentData(1)
	if err != nil {
		fmt.Printf("   错误: %v\n", err)
	} else {
		fmt.Printf("   压力: %.2f %s\n", record.Pressure, getPressureUnitName(record.PressureUnit))
		fmt.Printf("   电池: %d%%\n", record.BatteryLevel)
		fmt.Printf("   连接: %s\n", getConnectionStatus(record.ConnectionStatus))
		fmt.Printf("   信号: %d级\n", record.SignalLevel)
		fmt.Printf("   时间: %s\n", time.Unix(int64(record.Timestamp), 0).Format("2006-01-02 15:04:05"))
	}
}

// testWriteSubDevParam 测试写子设备参数
func testWriteSubDevParam(client modbus.Client) {
	// 测试设置压力单位
	fmt.Println("1. 测试设置变送器压力单位为 KPa")
	err := client.GatewayWriteSubDevParam(1, modbus.SubDevParamPressureUnit, modbus.PressureUnitKPa)
	if err != nil {
		fmt.Printf("   错误: %v\n", err)
	} else {
		fmt.Printf("   成功设置压力单位为 KPa\n")
	}

	// 测试设置变送器地址
	fmt.Println("2. 测试设置变送器地址为 2")
	err = client.GatewayWriteSubDevParam(1, modbus.SubDevParamTransmitterAddr, 2)
	if err != nil {
		fmt.Printf("   错误: %v\n", err)
	} else {
		fmt.Printf("   成功设置变送器地址为 2\n")
	}

	// 测试设置数据上报间隔
	fmt.Println("3. 测试设置数据上报间隔为 30 秒")
	err = client.GatewayWriteSubDevParam(1, modbus.SubDevParamDataReportInterval, 30)
	if err != nil {
		fmt.Printf("   错误: %v\n", err)
	} else {
		fmt.Printf("   成功设置数据上报间隔为 30 秒\n")
	}
}

// testWriteGatewayParam 测试写网关参数
func testWriteGatewayParam(client modbus.Client) {
	// 测试设置网关时间
	fmt.Println("1. 测试设置网关时间")
	currentTime := uint32(time.Now().Unix())
	err := client.GatewayWriteGatewayParam(65, modbus.GatewayParamTime, currentTime)
	if err != nil {
		fmt.Printf("   错误: %v\n", err)
	} else {
		fmt.Printf("   成功设置网关时间: %s\n",
			time.Unix(int64(currentTime), 0).Format("2006-01-02 15:04:05"))
	}

	// 测试设置RS485波特率
	fmt.Println("2. 测试设置RS485波特率为 9600")
	err = client.GatewayWriteGatewayParam(65, modbus.GatewayParamRS485Baudrate, 9600)
	if err != nil {
		fmt.Printf("   错误: %v\n", err)
	} else {
		fmt.Printf("   成功设置RS485波特率为 9600\n")
	}

	// 测试设置网关地址
	fmt.Println("3. 测试设置RS485地址为 66")
	err = client.GatewayWriteGatewayParam(65, modbus.GatewayParamRS485Address, 66)
	if err != nil {
		fmt.Printf("   错误: %v\n", err)
	} else {
		fmt.Printf("   成功设置RS485地址为 66\n")
	}
}

// 辅助函数
func getPressureUnitName(unit uint8) string {
	switch unit {
	case modbus.PressureUnitMbar:
		return "mbar"
	case modbus.PressureUnitBar:
		return "bar"
	case modbus.PressureUnitPsi:
		return "psi"
	case modbus.PressureUnitPa:
		return "Pa"
	case modbus.PressureUnitKPa:
		return "KPa"
	case modbus.PressureUnitMPa:
		return "MPa"
	case modbus.PressureUnitMmH2O:
		return "mmH2O"
	case modbus.PressureUnitMH2O:
		return "mH2O"
	case modbus.PressureUnitFtH2O:
		return "ftH2O"
	case modbus.PressureUnitInH2O:
		return "inH2O"
	default:
		return "unknown"
	}
}

func getConnectionStatus(status uint8) string {
	if status == 0 {
		return "断开"
	}
	return "连接"
}
